package com.dzh.ssm.common.aop.aspect;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class LoggingAspect {
	private static final String execution = "execution(int com.dzh.ssm.service.impl.*.*(..))";

	@Before(execution)
	public void beforeLog(JoinPoint jp) {
		String name = jp.getSignature().getName();
		List args = Arrays.asList(jp.getArgs());
		System.out.println("do before " + name + args);

	}

	// 在执行布标方法后执行,无论是否发生异常都会执行
	@After(execution)
	public void afterLog(JoinPoint jp) {
		String name = jp.getSignature().getName();
		List args = Arrays.asList(jp.getArgs());
		System.out.println("do after " + name + args);

	}

	// 方法结束后的通知
	// 注意 returning 的值要和 方法参数的的命名一样 如果报异常了就不会执行了
	@AfterReturning(value = execution, returning = "res")
	public void afterReturningLog(JoinPoint jp, Object res) {
		String name = jp.getSignature().getName();
		List args = Arrays.asList(jp.getArgs());
		System.out.println("do afterReturning " + name + args + " with result " + res);

	}

	// 异常通知
	@AfterThrowing(value = execution, throwing = "ex")
	public void afterThrowingLog(JoinPoint jp, Object ex) {
		String name = jp.getSignature().getName();
		List args = Arrays.asList(jp.getArgs());
		System.out.println("do afterReturning " + name + args + " with ex " + ex);

	}

	// 环绕通知 需要携带 ProceedingJoinPoint 类型的参数
	// 类似动态代理的全过程 ProceedingJoinPoint 可以界定是否执行目标方法
	// 也就是把动态代理执行目标方法的权限移交给了 用户
	
	
	@Around(value = execution)
	public Object aroundLog(ProceedingJoinPoint jp) {
		// 执行目标方法

		String name = jp.getSignature().getName();
		List args = Arrays.asList(jp.getArgs());

		Object result = null;
		try {
			// 前置通知
			System.out.println("do before " + name + args);
			result = jp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
			System.out.println("do afterReturning " + name + args + " with ex " + e);
		}

		// 后置通知
		System.out.println("do after " + name + args);

		return result;

	}

}
